package com.eye.admin.web;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import com.eye.admin.service.LogHelper;
import com.eye.admin.util.Permission;
import com.eye.admin.util.PermissionUtil;
import com.eye.core.utils.IpUtil;
import com.eye.core.utils.JacksonUtil;
import com.eye.core.utils.ResponseUtil;
import com.eye.db.domain.EyeAdmin;
import com.eye.db.service.EyeAdminService;
import com.eye.db.service.EyePermissionService;
import com.eye.db.service.EyeRoleService;

import javax.servlet.http.HttpServletRequest;

import static com.eye.admin.util.AdminResponseCode.ADMIN_INVALID_ACCOUNT;

import java.time.LocalDateTime;
import java.util.*;

@Api(description = "权限登录管理")
@RestController
@RequestMapping("/admin/auth")
@Validated
public class AdminAuthController {
	private final Log logger = LogFactory.getLog(AdminAuthController.class);

	@Autowired
	private EyeAdminService adminService;
	@Autowired
	private EyeRoleService roleService;
	@Autowired
	private EyePermissionService permissionService;
	@Autowired
	private LogHelper logHelper;

	/*
	 *  { username : value, password : value }
	 */
	@ApiOperation(value = "登录认证")
	@PostMapping("/login")
	public Object login(@RequestBody String body, HttpServletRequest request) {
		String username = JacksonUtil.parseString(body, "username");
		String password = JacksonUtil.parseString(body, "password");

		if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
			return ResponseUtil.badArgument();
		}

		Subject currentUser = SecurityUtils.getSubject();
		try {
			currentUser.login(new UsernamePasswordToken(username, password));
		} catch (UnknownAccountException uae) {
			logHelper.logAuthFail("登录", "用户帐号或密码不正确");
			return ResponseUtil.fail(ADMIN_INVALID_ACCOUNT, "用户帐号或密码不正确");
		} catch (LockedAccountException lae) {
			logHelper.logAuthFail("登录", "用户帐号已锁定不可用");
			return ResponseUtil.fail(ADMIN_INVALID_ACCOUNT, "用户帐号已锁定不可用");

		} catch (AuthenticationException ae) {
			logHelper.logAuthFail("登录", "认证失败");
			return ResponseUtil.fail(ADMIN_INVALID_ACCOUNT, "认证失败");
		}

		currentUser = SecurityUtils.getSubject();
		EyeAdmin admin = (EyeAdmin) currentUser.getPrincipal();
		admin.setLastLoginIp(IpUtil.getIpAddr(request));
		admin.setLastLoginTime(LocalDateTime.now());
		adminService.updateById(admin);

		logHelper.logAuthSucceed("登录");

		// userInfo
		Map<String, Object> adminInfo = new HashMap<String, Object>();
		adminInfo.put("nickName", admin.getUsername());
		adminInfo.put("avatar", admin.getAvatar());

		Map<Object, Object> result = new HashMap<Object, Object>();
		result.put("token", currentUser.getSession().getId());
		result.put("adminInfo", adminInfo);
		return ResponseUtil.ok(result);
	}

	/*
	 *
	 */
	@ApiOperation(value = "登出")
	@RequiresAuthentication
	@PostMapping("/logout")
	public Object logout() {
		Subject currentUser = SecurityUtils.getSubject();

		logHelper.logAuthSucceed("退出");
		currentUser.logout();
		return ResponseUtil.ok();
	}


	@ApiOperation(value = "获取账号信息")
	@RequiresAuthentication
	@GetMapping("/info")
	public Object info() {
		Subject currentUser = SecurityUtils.getSubject();
		EyeAdmin admin = (EyeAdmin) currentUser.getPrincipal();

		Map<String, Object> data = new HashMap<>();
		data.put("name", admin.getUsername());
		data.put("avatar", admin.getAvatar());

		Integer[] roleIds = admin.getRoleIds();
		Set<String> roles = roleService.queryByIds(roleIds);
		Set<String> permissions = permissionService.queryByRoleIds(roleIds);
		data.put("roles", roles);
		// NOTE
		// 这里需要转换perms结构，因为对于前端而已API形式的权限更容易理解
		data.put("perms", toApi(permissions));
		return ResponseUtil.ok(data);
	}

	@Autowired
	private ApplicationContext context;
	private HashMap<String, String> systemPermissionsMap = null;

	private Collection<String> toApi(Set<String> permissions) {
		if (systemPermissionsMap == null) {
			systemPermissionsMap = new HashMap<>();
			final String basicPackage = "com.eye.admin";
			//final String basicPckkage1 = "com.eye.admin";
			List<Permission> systemPermissions = PermissionUtil.listPermission(context, basicPackage);
			//List<Permission> permissions1 = PermissionUtil.listPermission(context, basicPckkage1);

			for (Permission permission : systemPermissions) {
				String perm = permission.getRequiresPermissions().value()[0];
				String api = permission.getApi();
				systemPermissionsMap.put(perm, api);
			}
			//for (Permission permission : permissions1) {
			//   String perm = permission.getRequiresPermissions().value()[0];
			//   String api = permission.getApi();
			//   systemPermissionsMap.put(perm, api);
			//            }
		}

		Collection<String> apis = new HashSet<>();
		for (String perm : permissions) {
			String api = systemPermissionsMap.get(perm);
			apis.add(api);

			if (perm.equals("*")) {
				apis.clear();
				apis.add("*");
				return apis;
				//                return systemPermissionsMap.values();

			}
		}
		return apis;
	}

	@ApiOperation(value = "不能登录报401")
	@GetMapping("/401")
	public Object page401() {
		return ResponseUtil.unlogin();
	}

	@ApiOperation(value = "登录详情")
	@GetMapping("/index")
	public Object pageIndex() {
		return ResponseUtil.ok();
	}

	@ApiOperation(value = "无操作权限报403")
	@GetMapping("/403")
	public Object page403() {
		return ResponseUtil.unauthz();
	}
}
